package com.arcsoft.api.base.handler;

import com.arcsoft.api.base.exception.CustomException;
import com.arcsoft.api.base.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;


@Slf4j
@RestControllerAdvice
public class ExceptionsHandler {


    /**
     * 请求路径无法找到异常
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public Result notFoundException() {
        return Result.fail("Not found", 404);
    }

    /**
     * 请求方法不支持异常
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result httpRequestMethodNotSupportedException() {
        return Result.fail("Method not allowed", 405);
    }

    /**
     * 请求参数异常
     */
    @ExceptionHandler({HttpMessageNotReadableException.class, MissingServletRequestParameterException.class, MissingServletRequestPartException.class})
    public Result parameterException() {
        return Result.fail("Parameter error", 403);
    }

    /**
     * 上传文件过大异常
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public Result maxUploadSizeExceededException() {
        return Result.fail("File is too large", 403);
    }


    @ExceptionHandler(CustomException.class)
    public Result customException(CustomException e) {
        return Result.fail(null, e.getMessage(), 500);
    }

    // <1> 处理 form data方式调用接口校验失败抛出的异常
    @ExceptionHandler(BindException.class)
    public Result bindExceptionHandler(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        String errorMsg = "";
        for (FieldError fieldError : fieldErrors) {
            errorMsg += ","+fieldError.getDefaultMessage();
        }
        return Result.fail(null,errorMsg.substring(1));
    }
    // <2> 处理 json 请求体调用接口校验失败抛出的异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        String errorMsg = "";
        for (FieldError fieldError : fieldErrors) {
            errorMsg += ","+fieldError.getDefaultMessage();
        }
        return Result.fail(null,errorMsg.substring(1));
    }
    // <3> 处理单个参数校验失败抛出的异常
    @ExceptionHandler(ConstraintViolationException.class)
    public Result constraintViolationExceptionHandler(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        String errorMsg = "";
        for (ConstraintViolation fieldError : constraintViolations) {
            errorMsg += ","+fieldError.getMessage();
        }
        return Result.fail(null,errorMsg.substring(1));
    }
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result<String> errorHandler(Exception ex) {
        ex.printStackTrace();
        return Result.fail("系统异常");
    }
}
